package com.learnyou.server.xingzuo.biz.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.learnyou.server.xingzuo.biz.IDeviceBiz;
import com.learnyou.server.xingzuo.common.util.AssertUtil;
import com.learnyou.server.xingzuo.dao.repository.entity.Account;
import com.learnyou.server.xingzuo.dao.repository.entity.Device;
import com.learnyou.server.xingzuo.dao.repository.service.IAccountService;
import com.learnyou.server.xingzuo.dao.repository.service.IDeviceService;
import com.learnyou.server.xingzuo.dto.paramDTO.pet.DeviceBaseInfoDTO;
import com.learnyou.server.xingzuo.dto.paramDTO.pet.DevicePingParamDTO;
import lombok.AllArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class DeviceBizImpl implements IDeviceBiz {

    private final IDeviceService deviceService;
    private final IAccountService accountService;
    private final RedisTemplate<String, String> redisTemplate;

    @Override
    public void ping(DevicePingParamDTO devicePingParamDTO) {
        Device device = checkAndGetDevice(devicePingParamDTO.getDeviceNo());
        //write redis
        redisTemplate.opsForValue().set(devicePingParamDTO.getDeviceNo(), devicePingParamDTO.getStatus(), 5, TimeUnit.MINUTES);
        //更新最后一次设备状态
        device.setStatus(devicePingParamDTO.getStatus());
        deviceService.updateById(device);
    }

    @Override
    public void registerAccount(String deviceNo, String phone) {
        Device device = checkAndGetDevice(deviceNo);

        List<Account> existAccounts = accountService.findByDeviceNo(deviceNo);

        Account account = new Account().setCode(deviceNo).setPhone(phone);
        if (CollUtil.isEmpty(existAccounts)) {
            //注册主账号
            accountService.save(account);
            device.setMasterAccount(account.getId());
            deviceService.updateById(device);
        }else {
            //注册子账号
            AssertUtil.checkCondition(existAccounts.stream().anyMatch(t-> StrUtil.equals(phone, t.getPhone())), "账号已注册！");
            accountService.save(account);
        }
    }

    private Device checkAndGetDevice(String deviceNo) {
        Device device = deviceService.findByDeviceNo(deviceNo);
        AssertUtil.isNull(device, "设备不存在！");
        return device;
    }

    @Override
    public void unbindAccount(String deviceNo, String phone) {
        Device device = checkAndGetDevice(deviceNo);
        Account account = accountService.findByDeviceNoAndPhone(deviceNo, phone);
        AssertUtil.isNull(account, "账号不存在！");
        AssertUtil.checkCondition(Objects.equals(account.getId(), device.getMasterAccount()), "主账号不能解绑！");

        accountService.removeById(account.getId());
    }

    @Override
    public List<String> getDevicesByAccount(String phone) {

        return accountService.findByPhone(phone).stream().map(Account::getCode).collect(Collectors.toList());
    }

    @Override
    public DeviceBaseInfoDTO getBaseInfo(String deviceNo) {
        Device device = checkAndGetDevice(deviceNo);
        DeviceBaseInfoDTO baseInfoDTO = BeanUtil.copyProperties(device, DeviceBaseInfoDTO.class);
        baseInfoDTO.setOnline(StrUtil.isNotEmpty(redisTemplate.opsForValue().get(deviceNo)));
        return baseInfoDTO;
    }

    @Override
    public void updateBaseInfo(DeviceBaseInfoDTO deviceBaseInfoDTO, Integer id) {
        Device device = BeanUtil.copyProperties(deviceBaseInfoDTO, Device.class, "code", "status");
        device.setId(id);
        deviceService.updateById(device);
    }
}
